package com.apobates.forum.member.service;

import com.apobates.forum.event.elderly.ForumActionEnum;
import com.apobates.forum.event.elderly.MemberActionDescriptor;
import com.apobates.forum.member.MemberProfileBean;
import com.apobates.forum.member.entity.*;
import com.apobates.forum.member.exception.MemberNamesExistException;
import com.apobates.forum.member.exception.MemberNamesProtectException;
import java.time.LocalDateTime;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.TreeMap;
import java.util.stream.Stream;

/**
 * 会员的业务层接口
 *
 * @author xiaofanku
 * @since 20200510
 */
public interface MemberService {
    /**
     * 根据会员的登录帐号搜索会员
     *
     * @param suggestNameWord 会员的登录帐号
     * @param pageSize 显示的数量
     * @return
     */
    Stream<Member> searchByNames(String suggestNameWord, int pageSize);
    
    /**
     * 根据会员的登录帐号搜索会员
     *
     * @param suggestNameWord 会员的登录帐号
     * @return
     */
    Stream<Member> searchByNames(String suggestNameWord);
    
    /**
     * 查看指定集合的会员信息
     *
     * @param idList 会员ID列表
     * @return
     */
    Stream<Member> queryCollection(List<Long> idList);
    
    /**
     * 最近注册的会员
     *
     * @param size 显示的数量
     * @return
     */
    Stream<Member> getRecent(int size);
    
    /**
     * 更新会员的登录密码
     *
     * @param id 会员ID
     * @param oldUnEncryptPswd 现在的密码
     * @param newUnEncryptPswd 更新后的密码
     * @param actionDescriptor 会员请求描述符
     * @return
     */
    Optional<Boolean> editPswd(long id, String oldUnEncryptPswd, String newUnEncryptPswd, MemberActionDescriptor actionDescriptor);
    
    /**
     * 更新会员的登录密码 找回密码的第二步
     *
     * @param id 会员ID
     * @param newUnEncryptPswd 新的密码
     * @param actionDescriptor 会员请求描述符
     * @return
     */
    Optional<Boolean> resetPswd(long id, String newUnEncryptPswd, MemberActionDescriptor actionDescriptor);
    
    /**
     * 更新会员的个性签名和昵称
     *
     * @param id 会员ID
     * @param signature 个性签名
     * @param nickname 网名/昵称
     * @param actionDescriptor 会员的操作统计
     * @return
     */
    Optional<Boolean> edit(long id, String signature, String nickname, MemberActionDescriptor actionDescriptor);
    
    /**
     * 更新会员头像
     *
     * @param id 会员ID
     * @param encodeAvtarFormatPath 编码后的头像路径
     * @param actionDescriptor 会员操作描述符
     * @return
     */
    Optional<Boolean> updateAvatar(long id, String encodeAvtarFormatPath, MemberActionDescriptor actionDescriptor);
    
    /**
     * 检查会员登录帐号的唯一性.如果是帐号保护也返回失败
     *
     * @param memberNames 会员登录帐号
     * @return 若想知道失败的原因可以使用:x.failureValue().getMessage()
     */
    Optional<Boolean> checkNamesUnique(String memberNames)throws MemberNamesProtectException,MemberNamesExistException;
    
    /**
     * 创建新的会员/注册会员, 操作成功后会发送通知(MemberSignUpEvent)
     *
     * @param memberNames 会员登录帐号
     * @param unEncryptPswd 未加密的密码
     * @param inviteCode 邀请码
     * @param nickname 昵称
     * @param actionDescriptor 会员请求描述符
     * @return 
     * 
     */
    Optional<Member> signUp(String memberNames, String unEncryptPswd, String inviteCode, String nickname, MemberActionDescriptor actionDescriptor)throws IllegalArgumentException,IllegalStateException;
    
    /**
     * 创建社区经理
     *
     * @param memberNames 登录帐号
     * @param unEncryptPswd 未加密的密码
     * @param nickname 会员昵称
     * @param role 角色
     * @param actionDescriptor 会员操作描述符
     * @return 
     * 
     */
    long create(String memberNames, String unEncryptPswd, String nickname, MemberRoleEnum role, MemberActionDescriptor actionDescriptor)throws IllegalArgumentException,IllegalStateException;
    
    /**
     * 查看指定的会员, 操作成功后会发送通知(MemberSignInEvent)
     *
     * @param memberNames 会员登录帐号
     * @param unEncryptPswd 未加密的密码
     * @param actionDescriptor 会员请求描述符
     * @return
     */
    Optional<Member> signIn(String memberNames, String unEncryptPswd, MemberActionDescriptor actionDescriptor)throws IllegalStateException;
    
    /**
     * 查看指定的会员
     *
     * @param memberNames 会员登录帐号
     * @param unEncryptPswd 未加密的密码
     * @param isAdmin 是否是管理员身份
     * @param actionDescriptor 会员请求描述符
     * @return
     */
    Optional<Member> signIn(String memberNames, String unEncryptPswd, boolean isAdmin, MemberActionDescriptor actionDescriptor)throws IllegalStateException;
    
    /**
     * 会员注销登录
     *
     * @param memberNames 会员登录帐号
     * @param member 会员
     * @param actionDescriptor 会员请求描述符
     * @return 
     */
    Optional<Boolean> signOut(String memberNames, Member member, MemberActionDescriptor actionDescriptor);

    /**
     * 将会员的默认组(CARD)提升至VIP
     * @deprecated
     * @param memberId 会员ID
     * @param duration 有效日期时长
     * @param unit 有效日期单位,只接受ForumCalendarUnitEnum.MONTH(月),只接受ForumCalendarUnitEnum.YEAR(年)
     * @throws IllegalStateException
     * @throws IllegalArgumentException
     * @return
     */
    Optional<Boolean> exchangeVIP(long memberId, int duration, ForumCalendarUnitEnum unit)throws IllegalStateException, IllegalArgumentException;

    /**
     * 将会员的默认组(CARD)提升至VIP
     *
     * @param memberId 会员ID
     * @param duration 有效日期时长
     * @param unit 有效日期单位,只接受ForumCalendarUnitEnum.MONTH(月),只接受ForumCalendarUnitEnum.YEAR(年)
     * @param transerial 交易流水号
     * @return
     * @throws IllegalStateException
     * @throws IllegalArgumentException
     */
    Optional<Boolean> exchangeVIP(long memberId, int duration, ForumCalendarUnitEnum unit, String transerial)throws IllegalStateException, IllegalArgumentException;

    /**
     * 查看指定的会员
     *
     * @param id 会员ID
     * @return
     */
    Optional<Member> get(long id);
    
    /**
     * 计算会员的个人汇总信息
     * @param id 会员ID
     * @param otherActionStats 非会员模块以外的操作统计
     * @return 
     */
    Optional<MemberProfileBean> calcMemberProfileBean(long id, Map<ForumActionEnum, Long> otherActionStats);
    
    /**
     * 查看会员的头像
     *
     * @param id 会员ID
     * @return
     */
    Optional<String> getMemberAvatar(long id);
    
    /**
     * 会员的登录帐号是否存在
     *
     * @param memberNames 会员登录帐号
     * @return 成功返回会员ID,不存在返回-1
     */
    long existMemberNames(String memberNames);
    
    /**
     * 会员合计
     *
     * @return
     */
    long count();
    
    /**
     * 统计指定日期范围内会员注册的数量
     *
     * @param start 开始日期
     * @param finish 结束日期
     * @return Key = YYYY-MM-DD, Value=注册数
     */
    TreeMap<String, Long> groupMemberForBirthDate(LocalDateTime start, LocalDateTime finish);
    
    /**
     * 分组统计不同状态的会员数量
     *
     * @return Key=Member.status, Value=会员数量
     */
    Map<MemberStatusEnum, Long> groupMemberForStatus();
    
    /**
     * 分组统计不同角色的会员数量
     *
     * @return Key=Member.mrole, Value=会员数量
     */
    Map<MemberRoleEnum, Long> groupMemberForRole();
    
    /**
     * 分组统计不同组的会员数量
     *
     * @return Key=Member.mgroup, Value=会员数量
     */
    Map<MemberGroupEnum, Long> groupMemberForGroup();
    
    /**
     * 查看指定的邀请码是否可用
     * 
     * @param inviteCode 邀请码
     * @return 返回的key：code(参数),id(可用时大于0,反之0)
     */
    Map<String,String> getActiveInviteCode(String inviteCode);
}